#include "utilities.h"

//This include the status request/response processing
void getProcessing(msg_header msgRespHdr, listBuffStruct eventReq)
{
	map<int,writeListData>::iterator it;
	list<getSTR>::iterator itR;
	list<fromUOIDStr>::iterator itF;
	if((uint8_t)msgRespHdr.msgtype == GTRQ)
	{
		if(printFlag==1)
		{
			cout<<"Got Get Request msg from - "<<eventReq.portNumber<<endl;
		}
		int testUOID = findInUOIDList(msgRespHdr.uoid);
		if(testUOID == 1)
		{

		}
		else
		{
			//Put the UOID in uoid queue
			uoidStr tempUOIDStr;
			struct timeval time1;
			gettimeofday(&time1, NULL);
			tempUOIDStr.timeOfTheDay = (double)(time1.tv_sec * (1e+3) + (double)time1.tv_usec/1000);
			tempUOIDStr.msgLifeTime = initMap["MsgLifetime"].asDouble;
			memcpy(tempUOIDStr.msgUOID, msgRespHdr.uoid, 20);
			pthread_mutex_lock(&uoidlock);
			myUOIDList.push_back(tempUOIDStr);
			pthread_mutex_unlock(&uoidlock);
			//if TTL is 1 then do not forward
			if(msgRespHdr.timetolive==1)
			{
				
			}
			else
			{
				//Forward the request to neighbors and reduce TTL by 1
				listBuffStruct lbtemp;
				lbtemp.logtype=2;
				int tempTTL = msgRespHdr.timetolive;
				tempTTL--;
				msgRespHdr.timetolive = tempTTL;
				memset(&lbtemp.listBuff, '\0', 8192);
				fillMsgHdrBuffer(msgRespHdr, lbtemp.listBuff);
				memcpy(&(lbtemp.listBuff[27]),&(eventReq.listBuff[27]),msgRespHdr.datalength);
				lbtemp.datalength = 27 + msgRespHdr.datalength;
				pthread_mutex_lock(&writeMapMutex);
				for(it=writeMap.begin(); it!=writeMap.end(); it++)
				{
					if((*it).first!=eventReq.portNumber)
					{
						//store the uoid in a map so that when it recieves a response then send it to the persone who initiated it.
						fromUOIDStr fromTemp;
						memcpy(fromTemp.uoid, &msgRespHdr.uoid, 20);
						fromTemp.portnumber = eventReq.portNumber;
						myFromUOIDList.push_back(fromTemp);
						lbtemp.portNumber = (*it).first;
						writeListData listDataStr = writeMap[(*it).first];
						listDataStr.response.push_back(lbtemp);
						writeMap[(*it).first] = listDataStr;
					}
				}
				pthread_mutex_unlock(&writeMapMutex);
			}
			//store the requested fileId and sha1.
			char fileId[20];
			char fileSha1[20];
			memset(fileId, '\0', 20);
			memset(fileSha1, '\0', 20);
			memcpy(&fileId, &(eventReq.listBuff[27]), 20);
			memcpy(&fileSha1, &(eventReq.listBuff[47]), 20);
			
			if(printFlag == 1)
			{
				cout<<"FileId - ";
				for(int n=0; n<20; n++)
				{
					printf("%02x", (uint8_t)fileId[n]);
				}
				cout<<endl;
				cout<<"FileSha1 - ";
				for(int n=0; n<20; n++)
				{
					printf("%02x", (uint8_t)fileSha1[n]);
				}
				cout<<endl;
			}
			
			list<search_fileId_results>::iterator itSearFileIds;
			int n = -1;
			int fileIndex = -1;
			//Get the fileIndex from the searchFileIdsList using the fileId sent in the request.
			for(itSearFileIds = searchFileIdsList.begin(); itSearFileIds != searchFileIdsList.end(); itSearFileIds++)
			{
				search_fileId_results temp = *itSearFileIds;
				n = memcmp(fileId, temp.fileUOID, 20);
				if(n == 0)
				{
					fileIndex = temp.fileIndex;
					break;
				}
			}
			//If the file is not present in the directory then just do not respond to the message
			if(fileIndex != -1)
			{
				//Store the size of the meta file
				char metaFile[512];
				memset(metaFile, '\0', 512);
				strcpy(metaFile,initMap["HomeDir"].asStr);
				strcat(metaFile,"/");
				strcat(metaFile,"files");
				strcat(metaFile,"/");
				char indx[5];
				memset(indx, '\0', 5);
				sprintf(indx, "%d", fileIndex);
				strcat(metaFile,indx);
				strcat(metaFile,".meta");
				struct stat st;
				int k = 0;
				k = stat(metaFile, &st);
				uint32_t metaSize = st.st_size;
				
				//Store the size of the data file
				char dataFile[512];
				memset(dataFile, '\0', 512);
				strcpy(dataFile,initMap["HomeDir"].asStr);
				strcat(dataFile,"/");
				strcat(dataFile,"files");
				strcat(dataFile,"/");
				strcat(dataFile,indx);
				strcat(dataFile,".data");
				k = stat(dataFile, &st);
				uint32_t dataSize = st.st_size;
				
				int forCounter = (20 + sizeof(uint32_t) + metaSize + dataSize)/(8192);
				int extraCounter = (20 + sizeof(uint32_t) + metaSize + dataSize)%(8192);
				
				//Prepare the get response header
				msg_header getRespHdr;
				char obj[256];
				char ch[8192];
				strcpy(obj, "GTRS");
				createMsgHdrStr(&getRespHdr,0xDB,initMap["TTL"].asDouble,obj,node_instance_id,20 + sizeof(uint32_t) + metaSize + dataSize);		
				
				//Prepare the get response data message
				//Also check if it exceeds the 8192 mark and insert into list accordingly.
				pthread_mutex_lock(&writeMapMutex);
				listBuffStruct lbtemp;
				lbtemp.logtype=1;
				memset(&lbtemp.listBuff, '\0', 8192);
				fillMsgHdrBuffer(getRespHdr, lbtemp.listBuff);
				lbtemp.datalength = 27;
				lbtemp.portNumber = eventReq.portNumber;
				writeListData listDataStr = writeMap[eventReq.portNumber];
				listDataStr.response.push_back(lbtemp);
				int f = 0;
				memset(ch, '\0', 8192);
				FILE *pFile1;
				pFile1 = fopen(metaFile,"r");
				fread(&ch,1,metaSize,pFile1);
				fclose(pFile1);
				memset(lbtemp.listBuff, '\0', 8192);
				memcpy(&(lbtemp.listBuff[0]), &(msgRespHdr.uoid[0]), 20);
				memcpy(&(lbtemp.listBuff[20]),&metaSize,sizeof(uint32_t));
				memcpy(&(lbtemp.listBuff[24]),&ch,metaSize);
				pFile1 = fopen(dataFile,"r");
				if(forCounter==0)
				{
					fread (&ch,1,dataSize,pFile1);
					memcpy(&(lbtemp.listBuff[24+metaSize]),&ch,dataSize);
					lbtemp.datalength = 20+4+metaSize+dataSize;
					listDataStr.response.push_back(lbtemp);
				}
				else
				{
					fread (&ch,1,8192-metaSize-sizeof(uint32_t)-20,pFile1);
					memcpy(&(lbtemp.listBuff[24+metaSize]),&ch,8192-metaSize-sizeof(uint32_t)-20);
					lbtemp.datalength = 8192;
					listDataStr.response.push_back(lbtemp);
					for(f=1;f<forCounter;f++)
					{
						fread (&ch,1,8192,pFile1);
						memset(lbtemp.listBuff,'\0',8192);
						lbtemp.datalength = 8192;
						memcpy(&(lbtemp.listBuff[0]),&ch,8192);
						listDataStr.response.push_back(lbtemp);
					}
					
					if(extraCounter!=0)
					{
						fread (&ch,1,extraCounter,pFile1);
						memset(lbtemp.listBuff,'\0',8192);
						lbtemp.datalength = extraCounter;
						memcpy(&(lbtemp.listBuff[0]),&ch,extraCounter);
						listDataStr.response.push_back(lbtemp);
					}
				}
				fclose(pFile1);
				writeMap[eventReq.portNumber] = listDataStr;
				pthread_mutex_unlock(&writeMapMutex);
			}
		}
	}
	else if((uint8_t)msgRespHdr.msgtype == GTRS)
	{
		if(printFlag==1)
		{
			cout<<"Got Get Response msg from - "<<eventReq.portNumber<<endl;
		}
		char UOIDtemp[20];
		memset(UOIDtemp, '\0', 20);
		listBuffStruct tempListBuff = eventQueue.front();
		memcpy(&UOIDtemp, &(tempListBuff.listBuff[0]), 20);
		//If I am the request initiator then store the response onto a .out file
		bool match = false;
		for(itR=getResponseList.begin(); itR!=getResponseList.end(); itR++)
		{
			getSTR temp = *itR;
			if(memcmp(UOIDtemp,temp.uoid,20)==0)
			{
				if(printFlag==1)
				{
					cout<<"MATCH FOUND"<<endl;
				}
				match = true;
				break;
			}
		}
		if(match==true)
		{
			if(printFlag == 1)
			{
				cout<<"Got response for my get request"<<endl;
			}
			
			int totalDataLength = msgRespHdr.datalength;
			int forCounter = totalDataLength/8192;
			int extraCounter = totalDataLength%8192;
			int f=0, j=0;
			
			pthread_mutex_lock(&eventQueueMutex);
			listBuffStruct tempListBuff = eventQueue.front();
			eventQueue.pop_front();
			pthread_mutex_unlock(&eventQueueMutex);
			char getRespUOID[20];
			memset(getRespUOID, '\0', 20);
			memcpy(&getRespUOID, &(tempListBuff.listBuff[0]), 20);
			uint32_t metaLength;
			memcpy(&metaLength,&(tempListBuff.listBuff[20]),sizeof(uint32_t));
			
			char metaData[512];
			memset(metaData, '\0', 512);
			memcpy(metaData, &(tempListBuff.listBuff[24]),metaLength);
			
			//Compare whether the file is same as stored/cached in our directory
			char sha1[20];
			char nonce[20];
			char fileNa[128];
			memset(sha1, '\0', 20);
			memset(nonce, '\0', 20);
			memset(fileNa, '\0', 128);
			
			extractNonShaFilN(metaData, fileNa, sha1, nonce);
			
			if(printFlag == 1)
			{
				cout<<"filena - "<<fileNa<<endl;
				cout<<"Sha1 - ";
				for(int l=0; l<20; l++)
				{
					printf("%02x", (uint8_t)sha1[l]);
				}
				cout<<endl;
				
				cout<<"nonce - ";
				for(int l=0; l<20; l++)
				{
					printf("%02x", (uint8_t)nonce[l]);
				}
				cout<<endl;
			}
			
			bool fileNotPresent = true;
			pthread_mutex_lock(&storelock);
			list<storeListStr>::iterator itStoreList;
			for(itStoreList=myStoreList.begin(); itStoreList!=myStoreList.end(); itStoreList++)
			{
				storeListStr temp = *itStoreList;
				if(strcmp(temp.fileName, fileNa) == 0)
				{
					if(memcmp(temp.fileSha1, sha1, 20) == 0)
					{
						if(memcmp(temp.fileNonce, nonce, 20) == 0)
						{
							fileNotPresent = false;
						}
					}
				}
			}
			pthread_mutex_unlock(&storelock);
			
			if(fileNotPresent)
			{
				if(printFlag == 1)
				{
					cout<<"File not present"<<endl;
				}
				FILE *pFile;
				pthread_mutex_lock(&fileCountsLock);
				int index = globalFileCounter;
				char fc[10];
				memset(fc,'\0',10);
				sprintf(fc,"%d",globalFileCounter++);
				pthread_mutex_unlock(&fileCountsLock);
				char storefilename[512];
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				mkdir(storefilename,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".meta");
				if(printFlag == 1)
				{
					cout<<storefilename<<endl;
				}
				pFile = fopen(storefilename,"w");
				if(pFile==NULL)
				{
					exit(0);
				}
				fwrite(&(tempListBuff.listBuff[24]),1,metaLength,pFile);
				fclose(pFile);
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".data");
				pFile = fopen(storefilename,"w");
				FILE* pFile1;
				
				if(getFile[0]=='\0')
				{
					char gFilename[200];
					memcpy(gFilename,&(tempListBuff.listBuff[33]),50);
					char*strx;
					strx=strtok(gFilename,"=");
					strx=strtok(NULL,"\n");
					if(printFlag == 1)
					{
						for(unsigned int p=0;p<strlen(strx);p++)
							printf("%c",strx[p]);
						cout<<endl;
					}
					memcpy(getFile,strx,strlen(strx));
				}
				
				bool fileReplace = true;
				pFile1 = fopen(getFile, "r");
				if(pFile1 != NULL)
				{
					char userInput[4];
					cout<<"Do you want the file to be replaced [yes/no] - ";
					cin>>userInput;
					fflush(stdin);
					if(userInput[0]=='y'||userInput[0]=='Y')
					{
						
					}
					else
					{
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						fileReplace = false;
					}
				}
				else
				{
					
				}
				fclose(pFile1);
				
				pFile1 = fopen(getFile,"w");
				if(forCounter==0)
				{
					if(printFlag == 1)
					{
						cout<<totalDataLength<<endl;
					}
					fwrite(&(tempListBuff.listBuff[24+metaLength]),1,totalDataLength-20-4-metaLength,pFile);
					if(fileReplace)
					{
						cout<<"File Has Been Created"<<endl;
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						fwrite(&(tempListBuff.listBuff[24+metaLength]),1,totalDataLength-20-4-metaLength,pFile1);
					}
				}
				else
				{
					fwrite(&(tempListBuff.listBuff[24+metaLength]),1,8192-20-4-metaLength,pFile);
					if(fileReplace)
					{
						cout<<"File Has Been Created"<<endl;
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						fwrite(&(tempListBuff.listBuff[24+metaLength]),1,8192-20-4-metaLength,pFile1);
					}
					for(f=1;f<forCounter;f++)
					{
						pthread_mutex_lock(&eventQueueMutex);
						tempListBuff = eventQueue.front();
						eventQueue.pop_front();
						pthread_mutex_unlock(&eventQueueMutex);
						fwrite(tempListBuff.listBuff,1,8192,pFile);
						if(fileReplace)
						{
							fwrite(tempListBuff.listBuff,1,8192,pFile1);
						}
					}
					if(extraCounter!=0)
					{
						pthread_mutex_lock(&eventQueueMutex);
						tempListBuff = eventQueue.front();
						eventQueue.pop_front();
						pthread_mutex_unlock(&eventQueueMutex);
						fwrite(tempListBuff.listBuff,1,extraCounter,pFile);
						if(fileReplace)
						{
							fwrite(tempListBuff.listBuff,1,extraCounter,pFile1);
						}
					}
				}
				fclose(pFile);
				fclose(pFile1);
				
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename, ".meta");
				pFile = fopen(storefilename,"r");
				char inputline[8192];
				char* findEquals;
				char* key;
				char* value;
				storeListStr storeData;
				while(fgets(inputline,sizeof(inputline),pFile))
				{
					remAllWhiteSpaces(inputline);
					//Find '=' which says its a key value pair
					findEquals = strchr(inputline, '=');
					if(findEquals == NULL)
					{
						continue;
					}
					else
					{
						key = strtok(inputline, "=");
						if(strcmp(key,"Filename")==0)
						{
							value = strtok(NULL, "=");
							value[strlen(value)-1] = '\0';						
							memcpy(storeData.fileName,value,strlen(value)+1);
						}
						if(strcmp(key,"Filesize")==0)
						{
							value = strtok(NULL, "=");
							value[strlen(value)-1] = '\0';						
							storeData.fileSize = atoi(value);
						}
						if(strcmp(key,"SHA1")==0)
						{
							value = strtok(NULL, "=");
							value[strlen(value)-1] = '\0';						
							convert40Bto20B(storeData.fileSha1,value);
						}
						if(strcmp(key,"Nonce")==0)
						{
							value = strtok(NULL, "=");
							value[strlen(value)-1] = '\0';						
							convert40Bto20B(storeData.fileNonce,value);
						}
						if(strcmp(key,"Bit-vector")==0)
						{
							value = strtok(NULL, "=");
							value[strlen(value)-1] = '\0';						
							memcpy(storeData.fileBitVector,value,strlen(value));
						}
					}
				}
				fclose(pFile);
				storeData.fileIndex = index;
				pthread_mutex_lock(&storelock);
				myStoreList.push_back(storeData);
				pthread_mutex_unlock(&storelock);
				
				//store in the kwrd_index file
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"kwrd_index");
				pFile=fopen(storefilename,"a");
				fprintf(pFile,"%d=",index);
				for(j=0;j<256;j++)
				{
					fprintf(pFile,"%c",storeData.fileBitVector[j]);
				}
				fprintf(pFile,"\n");
				fclose(pFile);

				//store in the name_index file
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"name_index");
				pFile=fopen(storefilename,"a");
				fprintf(pFile,"%d=",index);
				fprintf(pFile,"%s",storeData.fileName);
				fprintf(pFile,"\n");
				fclose(pFile);

				//store in the nonce_index file
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"nonce_index");
				pFile=fopen(storefilename,"a");
				fprintf(pFile,"%d=",index);
				for(j=0;j<20;j++)
				{
					fprintf(pFile,"%02x",(uint8_t)storeData.fileNonce[j]);
				}
				fprintf(pFile,"\n");
				fclose(pFile);

				//store in the sha1_index file
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"sha1_index");
				pFile=fopen(storefilename,"a");
				fprintf(pFile,"%d=",index);
				for(j=0;j<20;j++)
				{
					fprintf(pFile,"%02x",(uint8_t)storeData.fileSha1[j]);
				}
				fprintf(pFile,"\n");
				fclose(pFile);
			}
			else
			{
				if(printFlag == 1)
				{
					cout<<"File already present"<<endl;
				}
				FILE* pFile1;
				if(getFile[0]=='\0')
				{
					char gFilename[200];
					memcpy(gFilename,&(tempListBuff.listBuff[33]),50);
					char*strx;
					strx=strtok(gFilename,"=");
					strx=strtok(NULL,"\n");
					if(printFlag == 1)
					{
						for(unsigned int p=0;p<strlen(strx);p++)
							printf("%c",strx[p]);
						cout<<endl;
					}
					memcpy(getFile,strx,strlen(strx));
				}
				bool fileReplace = true;
				pFile1 = fopen(getFile, "r");
				if(pFile1 != NULL)
				{
					char userInput[4];
					cout<<"Do you want the file to be replaced [yes/no] - ";
					cin>>userInput;
					fflush(stdin);
					if(userInput[0]=='y'||userInput[0]=='Y')
					{
						
					}
					else
					{
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						fileReplace = false;
					}
				}
				else
				{
					
				}
				fclose(pFile1);
				
				if(fileReplace)
				{
					pFile1 = fopen(getFile,"w");
					if(forCounter==0)
					{
						fwrite(&(tempListBuff.listBuff[24+metaLength]),1,totalDataLength-20-4-metaLength,pFile1);
					}
					else
					{
						fwrite(&(tempListBuff.listBuff[24+metaLength]),1,8192-20-4-metaLength,pFile1);
						for(f=1;f<forCounter;f++)
						{
							pthread_mutex_lock(&eventQueueMutex);
							tempListBuff = eventQueue.front();
							eventQueue.pop_front();
							pthread_mutex_unlock(&eventQueueMutex);
							fwrite(tempListBuff.listBuff,1,8192,pFile1);
						}
						if(extraCounter!=0)
						{
							pthread_mutex_lock(&eventQueueMutex);
							tempListBuff = eventQueue.front();
							eventQueue.pop_front();
							pthread_mutex_unlock(&eventQueueMutex);
							fwrite(tempListBuff.listBuff,1,extraCounter,pFile1);
						}
					}
					fclose(pFile1);
					cout<<"File Has Been Created"<<endl;
					cout<<"servant:"<<port_recieve<<"> ";
					fflush(stdout);
							
				}
			}
		}
		else
		{
			if(printFlag == 1)
			{
				cout<<"Resp forward time"<<endl;
			}
			int totalDataLength = msgRespHdr.datalength;
			int forCounter = totalDataLength/8192;
			int extraCounter = totalDataLength%8192;
			listBuffStruct tempListBuff = eventQueue.front();
			char responseUOID[20];
			memset(responseUOID, '\0', 20);
			memcpy(&responseUOID, &(tempListBuff.listBuff[0]), 20);
			uint32_t metaLength;
			memcpy(&metaLength,&(tempListBuff.listBuff[20]),sizeof(uint32_t));
			
			//Compare whether the file is same as stored/cached in our directory
			char metaData[512];
			memset(metaData, '\0', 512);
			memcpy(metaData, &(tempListBuff.listBuff[24]),metaLength);
			
			char sha1[20];
			char nonce[20];
			char fileNa[128];
			memset(sha1, '\0', 20);
			memset(nonce, '\0', 20);
			memset(fileNa, '\0', 128);
			
			extractNonShaFilN(metaData, fileNa, sha1, nonce);
			
			bool fileNotPresent = true;
			pthread_mutex_lock(&storelock);
			list<storeListStr>::iterator itStoreList;
			int index = -1;
			char fc[10];
			char storefilename[512];
					
			for(itStoreList=myStoreList.begin(); itStoreList!=myStoreList.end(); itStoreList++)
			{
				storeListStr temp = *itStoreList;
				if(strcmp(temp.fileName, fileNa) == 0)
				{
					if(memcmp(temp.fileSha1, sha1, 20) == 0)
					{
						if(memcmp(temp.fileNonce, nonce, 20) == 0)
						{
							fileNotPresent = false;
							index = temp.fileIndex;
							memset(fc,'\0',10);
							sprintf(fc,"%d",index);
						}
					}
				}
			}
			pthread_mutex_unlock(&storelock);
			
			int f = 0;
			int noForwardingFlag = 0;
			if(fileNotPresent)
			{
				if(printFlag == 1)
				{
					cout<<"Resp forward file not present"<<endl;
				}
				if(totalDataLength > initMap["CacheSize"].asDouble*1000||drand48()>initMap["CacheProb"].asDouble)
				{
					if(printFlag == 1)
					{
						cout<<"File too big to be stored in this cache or Cacheprob"<<endl;
					}
					
					if(msgRespHdr.timetolive==1||noForwardingFlag == 1)
					{
						if(printFlag == 1)
						{
						cout<<"TTl or NoForwarding "<<noForwardingFlag<<" Problem"<<endl;
						}
					}
					else
					{
						if(printFlag == 1)
						{
							cout<<"--foward"<<endl;
						}
						pthread_mutex_lock(&writeMapMutex);
						pthread_mutex_lock(&eventQueueMutex);
						listBuffStruct lbtemp;
						lbtemp.logtype=2;
						int tempTTL = msgRespHdr.timetolive;
						tempTTL--;
						msgRespHdr.timetolive = tempTTL;
						memset(lbtemp.listBuff, '\0', 8192);
						fillMsgHdrBuffer(msgRespHdr, lbtemp.listBuff);
						lbtemp.datalength = 27;
						lbtemp.portNumber = eventReq.portNumber;
						int getResPortnmber = 0;
						for(itF=myFromUOIDList.begin(); itF!=myFromUOIDList.end(); itF++)
						{
							fromUOIDStr temp = *itF;
							if(memcmp(UOIDtemp,temp.uoid,20)==0)
							{
								getResPortnmber = temp.portnumber;
								break;
							}
						}
						writeListData listDataStr = writeMap[getResPortnmber];
						listDataStr.response.push_back(lbtemp);
						tempListBuff = eventQueue.front();
						eventQueue.pop_front();
						if(printFlag == 1)
						{
							cout<<"forcounter "<<forCounter<<endl;
							cout<<"extracounter "<<extraCounter<<endl;
							printf("%s\n",&(tempListBuff.listBuff[24]));
						}
						if(forCounter==0)
						{
							memset(lbtemp.listBuff, '\0', extraCounter);
							memcpy(lbtemp.listBuff, tempListBuff.listBuff, extraCounter);
							lbtemp.datalength = extraCounter;
							listDataStr.response.push_back(lbtemp);
						}
						else
						{
							memset(lbtemp.listBuff, '\0', 8192);
							memcpy(lbtemp.listBuff, &(tempListBuff.listBuff[0]), 8192);
							lbtemp.datalength = 8192;
							listDataStr.response.push_back(lbtemp);
							for(f=1;f<forCounter;f++)
							{
								tempListBuff = eventQueue.front();
								eventQueue.pop_front();
								memset(lbtemp.listBuff, '\0', 8192);
								memcpy(lbtemp.listBuff, &(tempListBuff.listBuff[0]), 8192);
								lbtemp.datalength = 8192;
								listDataStr.response.push_back(lbtemp);
							}
							if(extraCounter!=0)
							{
								tempListBuff = eventQueue.front();
								eventQueue.pop_front();
								memset(lbtemp.listBuff, '\0', extraCounter);
								memcpy(lbtemp.listBuff, &(tempListBuff.listBuff[0]), extraCounter);
								lbtemp.datalength = extraCounter;
								listDataStr.response.push_back(lbtemp);
							}
						}
						writeMap[getResPortnmber]=listDataStr;
						pthread_mutex_unlock(&eventQueueMutex);
						pthread_mutex_unlock(&writeMapMutex);
					}
					return;
					//File too big
				}
				pthread_mutex_lock(&cacheSizeLock);
				while(currentCacheSize + totalDataLength - metaLength > initMap["CacheSize"].asDouble*1000)
				{
					//cache size is exceeding
					if(printFlag == 1)
					{
						cout<<"Cache Problem Current Size"<<currentCacheSize<<endl;
					}
					pthread_mutex_lock(&LRULock);
					int indexRemoved = LRUList.front();
					LRUList.pop_front();
					pthread_mutex_unlock(&LRULock);
					list<storeListStr>::iterator itF;
					char filename[512];
					FILE *pFile;
					pthread_mutex_lock(&storelock);
					for(itF=myStoreList.begin(); itF!=myStoreList.end(); itF++)
					{
						storeListStr storeTemp = *itF;
						if(storeTemp.fileIndex==indexRemoved)
						{
							if(printFlag == 1)
							{
								cout<<"Cached File Found"<<endl;
							}
							int index = storeTemp.fileIndex;
							if(printFlag == 1)
							{
								cout<<index<<endl;
							}
							char fc[10];
							memset(fc,'\0',10);
							sprintf(fc,"%d",index);
							if(printFlag == 1)
							{
								cout<<"Match Found Deleting File"<<endl;
							}
							strcpy(storefilename,initMap["HomeDir"].asStr);
							strcat(storefilename,"/");
							strcat(storefilename,"files");
							strcat(storefilename,"/");
							strcat(storefilename,fc);
							char deletefilename[8192];
							memset(deletefilename,'\0',8192);
							strcpy(deletefilename,storefilename);
							strcat(deletefilename,".data");
							if( remove(deletefilename) != 0 )
							{
								perror( "Error deleting file" );
							}
							else
							{
								if(printFlag == 1)
								{
									printf("%s.data File successfully deleted\n",fc );
								}
							}
							memset(deletefilename,'\0',8192);
							strcpy(deletefilename,storefilename);
							strcat(deletefilename,".meta");
							if( remove(deletefilename) != 0 )
							{
								perror( "Error deleting file" );
							}
							else
							{
								if(printFlag == 1)
								{
									printf("%s.meta File successfully deleted\n",fc );
								}
							}
							currentCacheSize = currentCacheSize - storeTemp.fileSize;
							if(printFlag == 1)
							{	
								cout<<myStoreList.size()<<endl;
							}
							itF = myStoreList.erase(itF);
							if(printFlag == 1)
							{
								cout<<myStoreList.size()<<endl;
							}
						}							
					}
					
					strcpy(storefilename,initMap["HomeDir"].asStr);
					strcat(storefilename,"/");
					strcpy(filename,storefilename);
					strcat(filename,"kwrd_index");
					pFile=fopen(filename,"w");
					fclose(pFile);
					strcpy(filename,storefilename);
					strcat(filename,"sha1_index");
					pFile=fopen(filename,"w");
					fclose(pFile);
					strcpy(filename,storefilename);
					strcat(filename,"nonce_index");
					pFile=fopen(filename,"w");
					fclose(pFile);
					strcpy(filename,storefilename);
					strcat(filename,"name_index");
					pFile=fopen(filename,"w");
					fclose(pFile);
					if(printFlag == 1)
					{
						cout<<myStoreList.size()<<endl;
					}
					for(itF=myStoreList.begin(); itF!=myStoreList.end(); itF++)
					{
						if(printFlag == 1)
						{
							cout<<"enters"<<endl;
						}
						storeListStr storeData = *itF;
						strcpy(filename,initMap["HomeDir"].asStr);
						strcat(filename,"/");
						strcat(filename,"kwrd_index");
						pFile=fopen(filename,"a");
						fprintf(pFile,"%d=",storeData.fileIndex);
						int j =0;
						for(j=0;j<256;j++)
						{
							fprintf(pFile,"%c",storeData.fileBitVector[j]);
						}
						fprintf(pFile,"\n");
						fclose(pFile);

						//Create the name_index file
						strcpy(filename,initMap["HomeDir"].asStr);
						strcat(filename,"/");
						strcat(filename,"name_index");
						pFile=fopen(filename,"a");
						fprintf(pFile,"%d=",storeData.fileIndex);
						fprintf(pFile,"%s",storeData.fileName);
						fprintf(pFile,"\n");
						fclose(pFile);

						//Create the nonce_index file
						strcpy(filename,initMap["HomeDir"].asStr);
						strcat(filename,"/");
						strcat(filename,"nonce_index");
						pFile=fopen(filename,"a");
						fprintf(pFile,"%d=",storeData.fileIndex);
						for(j=0;j<20;j++)
						{
							fprintf(pFile,"%02x",(uint8_t)storeData.fileNonce[j]);
						}
						fprintf(pFile,"\n");
						fclose(pFile);

						//Create the sha1_index file
						strcpy(filename,initMap["HomeDir"].asStr);
						strcat(filename,"/");
						strcat(filename,"sha1_index");
						pFile=fopen(filename,"a");
						fprintf(pFile,"%d=",storeData.fileIndex);
						for(j=0;j<20;j++)
						{
							fprintf(pFile,"%02x",(uint8_t)storeData.fileSha1[j]);
						}
						fprintf(pFile,"\n");
						fclose(pFile);
					}
					pthread_mutex_unlock(&storelock);
				}
				
				if(printFlag == 1)
				{
					cout<<"No problem storing part"<<endl;
				}
				pthread_mutex_unlock(&cacheSizeLock);
				
				pthread_mutex_lock(&eventQueueMutex);
				tempListBuff = eventQueue.front();
				eventQueue.pop_front();
				pthread_mutex_unlock(&eventQueueMutex);
				FILE *pFile;
				pthread_mutex_lock(&fileCountsLock);
				index = globalFileCounter;
				memset(fc,'\0',10);
				sprintf(fc,"%d",globalFileCounter++);
				pthread_mutex_unlock(&fileCountsLock);
				char storefilename[512];
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				mkdir(storefilename,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".meta");
				if(printFlag == 1)
				{
					cout<<storefilename<<endl;
				}
				pFile = fopen(storefilename,"w");
				if(pFile==NULL)
				{
					exit(0);
				}
				fwrite(&(tempListBuff.listBuff[24]),1,metaLength,pFile);
				fclose(pFile);
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".data");
				pFile = fopen(storefilename,"w");
				if(forCounter==0)
				{
					if(printFlag == 1)
					{
						cout<<totalDataLength<<endl;
					}
					fwrite(&(tempListBuff.listBuff[24+metaLength]),1,totalDataLength-24-metaLength,pFile);
				}
				else
				{
					fwrite(&(tempListBuff.listBuff[24+metaLength]),1,8192-24-metaLength,pFile);
					for(f=1;f<forCounter;f++)
					{
						pthread_mutex_lock(&eventQueueMutex);
						tempListBuff = eventQueue.front();
						eventQueue.pop_front();
						pthread_mutex_unlock(&eventQueueMutex);
						fwrite(tempListBuff.listBuff,1,8192,pFile);
					}
					if(extraCounter!=0)
					{
						pthread_mutex_lock(&eventQueueMutex);
						tempListBuff = eventQueue.front();
						eventQueue.pop_front();
						pthread_mutex_unlock(&eventQueueMutex);
						fwrite(tempListBuff.listBuff,1,extraCounter,pFile);
					}
				}
				fclose(pFile);
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				noForwardingFlag = meta_file_parsing(storefilename,index);
			}
			else
			{
				//LRU update
				
			}
			
			if(msgRespHdr.timetolive==1||noForwardingFlag == 1)
			{
				if(printFlag == 1)
				{
					cout<<"TTl or NoForwarding "<<noForwardingFlag<<" Problem"<<endl;
				}
				//no forwarding
			}
			else
			{
				if(printFlag == 1)
				{
					cout<<"--foward"<<endl;
				}
				pthread_mutex_lock(&writeMapMutex);
				listBuffStruct lbtemp;
				lbtemp.logtype=2;
				int tempTTL = msgRespHdr.timetolive;
				tempTTL--;
				msgRespHdr.timetolive = tempTTL;
				struct stat st;
				int k = 0;
				char ch[8192];
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".meta");
				k = stat(storefilename, &st);
				uint32_t sz = st.st_size;
				memset(lbtemp.listBuff, '\0', 8192);
				fillMsgHdrBuffer(msgRespHdr, lbtemp.listBuff);
				lbtemp.datalength = 27;
				lbtemp.portNumber = eventReq.portNumber;
				int getResPortnmber = 0;
				for(itF=myFromUOIDList.begin(); itF!=myFromUOIDList.end(); itF++)
				{
					fromUOIDStr temp = *itF;
					if(memcmp(UOIDtemp,temp.uoid,20)==0)
					{
						getResPortnmber = temp.portnumber;
						break;
					}
				}
				writeListData listDataStr = writeMap[getResPortnmber];
				listDataStr.response.push_back(lbtemp);
				FILE *pFile1;
				pFile1 = fopen(storefilename,"r");
				fread(&ch,1,sz,pFile1);
				memset(lbtemp.listBuff, '\0', 8192);
				memcpy(&(lbtemp.listBuff[0]), &responseUOID, 20); 
				memcpy(&(lbtemp.listBuff[20]),&sz,sizeof(uint32_t));
				memcpy(&(lbtemp.listBuff[24]),&ch,sz);
				fclose(pFile1);
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".data");
				pFile1 = fopen(storefilename,"r");
				if(forCounter==0)
				{
					fread (&ch,1,totalDataLength-24-sz,pFile1);
					memcpy(&(lbtemp.listBuff[24+sz]),&ch,totalDataLength-24-sz);
					lbtemp.datalength = totalDataLength;
					listDataStr.response.push_back(lbtemp);
				}
				else
				{
					fread (&ch,1,8192-sz-sizeof(uint32_t)-20,pFile1);
					memcpy(&(lbtemp.listBuff[24+sz]),&ch,8192-sz-sizeof(uint32_t)-20);
					lbtemp.datalength = 8192;
					listDataStr.response.push_back(lbtemp);
					for(f=1;f<forCounter;f++)
					{
						fread (&ch,1,8192,pFile1);
						memset(lbtemp.listBuff,'\0',8192);
						lbtemp.datalength = 8192;
						memcpy(&(lbtemp.listBuff[0]),&ch,8192);
						listDataStr.response.push_back(lbtemp);
					}
					if(extraCounter!=0)
					{
						fread (&ch,1,extraCounter,pFile1);
						memset(lbtemp.listBuff,'\0',8192);
						lbtemp.datalength = extraCounter;
						memcpy(&(lbtemp.listBuff[0]),&ch,extraCounter);
						listDataStr.response.push_back(lbtemp);
					}
				}
				fclose(pFile1);
				writeMap[getResPortnmber] = listDataStr;
				pthread_mutex_unlock(&writeMapMutex);
			}
			
		}
	}
}
